package com.cq.hd.member.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cq.hd.common.constant.Constant;
import com.cq.hd.common.constant.MsgConstant;
import com.cq.hd.common.constant.RedisKeyConstant;
import com.cq.hd.common.entity.BusinessInfo;
import com.cq.hd.common.entity.MerchantUserInfo;
import com.cq.hd.common.entity.hf.HfBusinessEnterApply;
import com.cq.hd.common.entity.hf.HfBusinessEnterApplyResult;
import com.cq.hd.common.entity.mq.NotifyMsgSendDto;
import com.cq.hd.common.enums.ResponseEnums;
import com.cq.hd.common.enums.biz.*;
import com.cq.hd.common.exception.BusinessException;
import com.cq.hd.common.pagination.Page;
import com.cq.hd.common.response.Throw;
import com.cq.hd.common.utils.*;
import com.cq.hd.member.api.dto.*;
import com.cq.hd.member.api.vo.*;
import com.cq.hd.member.biz.SmsBiz;
import com.cq.hd.member.config.LockUtils;
import com.cq.hd.member.config.WxConfig;
import com.cq.hd.member.mapper.*;
import com.cq.hd.member.mq.provider.MerchantEnterMsgProvider;
import com.cq.hd.member.mq.provider.NotifyMsgProvider;
import com.cq.hd.member.po.*;
import com.cq.hd.member.service.TbMerchantEnterApplyService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cq.hd.system.api.HfApi;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.text.MessageFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 商户入驻申请记录表 服务实现类
 * </p>
 *
 * @author mYunYu
 * @since 2023-11-21
 */
@Slf4j
@Service
public class TbMerchantEnterApplyServiceImpl extends ServiceImpl<TbMerchantEnterApplyMapper, TbMerchantEnterApplyPo> implements TbMerchantEnterApplyService {

    @Autowired
    private TbBusinessMapper businessMapper;

    @Autowired
    private TbMerchantMapper merchantMapper;

    @Autowired
    private TbBusinessMerchantMapper businessMerchantMapper;

    @Autowired
    private TbPopRecordMapper popRecordMapper;

    @Autowired
    private TbBusinessEnterApplyMapper businessEnterApplyMapper;

    @Autowired
    private PlatformTransactionManager transactionManager;

    @Autowired
    private HfApi hfApi;

    @Autowired
    private MerchantEnterMsgProvider merchantEnterMsgProvider;

    @Autowired
    private NotifyMsgProvider notifyMsgProvider;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private SmsBiz smsBiz;

    @Value("${spring.profiles.active}")
    private String env;

    @Override
    public Integer getAuditCount(Long businessId) {
        TbBusinessPo tbBusinessPo = businessMapper.selectById(businessId);
        if (tbBusinessPo == null || StringUtils.isBlank(tbBusinessPo.getInviteCode())) {
            return 0;
        }

        Integer count = baseMapper.selectCount(new QueryWrapper<TbMerchantEnterApplyPo>().eq("del_state", 0)
                .eq("audit_state", AuditStateEnum.WAIT_AUDIT.getValue())
                .eq("system_audit_state", SystemAuditStateEnum.MANAGER_WAIT_AUDIT.getValue())
                .eq("settle_code", tbBusinessPo.getInviteCode()));

        return count == null ? 0 : count;
    }

    @Override
    public Page<AppMerchantEnterApplyPageVo> pageAppMerchantEnterApply(AppMerchantEnterApplyPageDto appMerchantEnterApplyPageDto) {
        Long businessId = appMerchantEnterApplyPageDto.getBusinessId();
        if (businessId == null) {
            Long userId = appMerchantEnterApplyPageDto.getUserId();
            List<TbBusinessPo> tbBusinessPos = businessMapper.selectList(new QueryWrapper<TbBusinessPo>().eq("del_state", 0)
                    .eq("state", 1).eq("user_id", userId));
            if (CollectionUtils.isEmpty(tbBusinessPos)) {
                return new Page<>();
            }

            appMerchantEnterApplyPageDto.setBusinessId(tbBusinessPos.get(0).getId());
            appMerchantEnterApplyPageDto.setInviteCode(tbBusinessPos.get(0).getInviteCode());
        } else {
            TbBusinessPo tbBusinessPo = businessMapper.selectById(businessId);
            if (tbBusinessPo == null || StringUtils.isBlank(tbBusinessPo.getInviteCode())) {
                return new Page<>();
            }

            appMerchantEnterApplyPageDto.setInviteCode(tbBusinessPo.getInviteCode());
        }

        PageHelper.startPage(appMerchantEnterApplyPageDto.getPageNum(), appMerchantEnterApplyPageDto.getPageSize());
        List<AppMerchantEnterApplyPageVo> appMerchantEnterApplyPageVos = baseMapper.listAppMerchantEnterApplyByDto(appMerchantEnterApplyPageDto);
        PageInfo<AppMerchantEnterApplyPageVo> pageInfo = new PageInfo<>(appMerchantEnterApplyPageVos);
        return Page.newPageWithAllFields(pageInfo.getList(), pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getTotal(), pageInfo.getPages());
    }

    @Override
    public Page<AdminMerchantEnterApplyPageVo> pageAdminMerchantEnterApply(MerchantEnterApplyPageDto merchantEnterApplyPageDto) {
        Long businessId = merchantEnterApplyPageDto.getBusinessId();
        if (businessId != null) {
            TbBusinessPo tbBusinessPo = businessMapper.selectById(businessId);
            if (tbBusinessPo == null || StringUtils.isBlank(tbBusinessPo.getInviteCode())) {
                return new Page<>();
            }

            merchantEnterApplyPageDto.setInviteCode(tbBusinessPo.getInviteCode());
        }

        PageHelper.startPage(merchantEnterApplyPageDto.getPageNum(), merchantEnterApplyPageDto.getPageSize());
        List<AdminMerchantEnterApplyPageVo> appMerchantEnterApplyPageVos = baseMapper.listAdminMerchantEnterApplyByDto(merchantEnterApplyPageDto);
        PageInfo<AdminMerchantEnterApplyPageVo> pageInfo = new PageInfo<>(appMerchantEnterApplyPageVos);
        return Page.newPageWithAllFields(pageInfo.getList(), pageInfo.getPageNum(), pageInfo.getPageSize(), pageInfo.getTotal(), pageInfo.getPages());
    }

    @Override
    public AppMerchantEnterApplyPageVo details(Long id) {
        TbMerchantEnterApplyPo tbMerchantEnterApplyPo = baseMapper.selectById(id);
        if (tbMerchantEnterApplyPo != null) {
            AppMerchantEnterApplyPageVo appMerchantEnterApplyPageVo = new AppMerchantEnterApplyPageVo();
            BeanUtils.copyProperties(tbMerchantEnterApplyPo, appMerchantEnterApplyPageVo);

            // 银行编号
            String bankCode = appMerchantEnterApplyPageVo.getBankCode();
            if (!StringUtils.isBlank(bankCode)) {
                HfBankIdEnum hfBankIdEnum = HfBankIdEnum.typeOfValue(bankCode);
                if (hfBankIdEnum != null) {
                    appMerchantEnterApplyPageVo.setBankName(hfBankIdEnum.getName());
                }
            }

            // 持卡人证件类型
            String certType = appMerchantEnterApplyPageVo.getCertType();
            if (!StringUtils.isBlank(certType)) {
                CertTypeEnum certTypeEnum = CertTypeEnum.typeOfValue(certType);
                if (certTypeEnum != null) {
                    appMerchantEnterApplyPageVo.setCertType(certTypeEnum.getName());
                }
            }

            // 法人证件类型
            String legalCertType = appMerchantEnterApplyPageVo.getLegalCertType();
            if (!StringUtils.isBlank(legalCertType)) {
                CertTypeEnum certTypeEnum = CertTypeEnum.typeOfValue(legalCertType);
                if (certTypeEnum != null) {
                    appMerchantEnterApplyPageVo.setLegalCertType(certTypeEnum.getName());
                }
            }

            return appMerchantEnterApplyPageVo;
        }
        return null;
    }

    @Override
    public Boolean audit(MerchantEnterAuditDto merchantEnterAuditDto) {
        AuditStateEnum auditStateEnum = AuditStateEnum.typeOf(merchantEnterAuditDto.getAuditState());
        if (auditStateEnum == null) {
            Throw.isBusinessException("审核状态错误");
        }

        TbMerchantEnterApplyPo tbMerchantEnterApplyPo = baseMapper.selectById(merchantEnterAuditDto.getId());
        if (tbMerchantEnterApplyPo == null) {
            Throw.isBusinessException("未找到入驻记录数据");
        }

        if (!AuditStateEnum.WAIT_AUDIT.getValue().equals(tbMerchantEnterApplyPo.getAuditState())
                && !SystemAuditStateEnum.MANAGER_WAIT_AUDIT.getValue().equals(tbMerchantEnterApplyPo.getSystemAuditState())) {
            Throw.isBusinessException("入驻记录已被审核");
        }

        List<TbBusinessPo> tbBusinessPos = businessMapper.selectList(new QueryWrapper<TbBusinessPo>().eq("del_state", 0)
                .eq("invite_code", tbMerchantEnterApplyPo.getSettleCode()));
        TbBusinessPo tbBusinessPo = tbBusinessPos.get(0);
        String hfMerchantNo = tbBusinessPo.getHfMerchantNo();

        LocalDateTime now = LocalDateTime.now();

        if (AuditStateEnum.FAIL.getValue().equals(merchantEnterAuditDto.getAuditState())) {
            tbMerchantEnterApplyPo.setAuditState(AuditStateEnum.FAIL.getValue());
            tbMerchantEnterApplyPo.setSystemAuditState(SystemAuditStateEnum.MANAGER_AUDIT_FAIL.getValue());
            tbMerchantEnterApplyPo.setRefuseReason(merchantEnterAuditDto.getRefuseReason());
        } else if (AuditStateEnum.SUCCESS.getValue().equals(merchantEnterAuditDto.getAuditState())) {
            // 测试环境不走汇付
            log.info("商户入驻审核，env:{}", env);
//            if ("test".equals(env)) {
//                tbMerchantEnterApplyPo.setAuditState(AuditStateEnum.SUCCESS.getValue());
//            } else {

            if (SystemAuditStateEnum.MANAGER_WAIT_AUDIT.getValue().equals(tbMerchantEnterApplyPo.getSystemAuditState())) {
                HfBusinessEnterApplyResult hfBusinessEnterApplyResult = null;
                HfBusinessEnterApply hfBusinessEnterApply = new HfBusinessEnterApply();
                // 账户结算类型(1-个人账户结算，2-对公账户结算)
                Integer settlementType = tbMerchantEnterApplyPo.getSettlementType();
                if (settlementType == 1) {
                    BeanUtils.copyProperties(tbMerchantEnterApplyPo, hfBusinessEnterApply);
                    hfBusinessEnterApply.setBusinessName(tbMerchantEnterApplyPo.getMerchantName());
                    hfBusinessEnterApply.setBusinessShortName(tbMerchantEnterApplyPo.getMerchantShortName());
                    // 入驻角色类型：1-商家，2-商户
                    hfBusinessEnterApply.setEnterType(2);
                    hfBusinessEnterApply.setParentHfMerchantNo(hfMerchantNo);
                    hfBusinessEnterApplyResult = hfApi.merchantEntIndv(hfBusinessEnterApply).unpack();
                    if (StringUtils.isBlank(hfBusinessEnterApplyResult.getHuiFuId())) {
                        log.error("商户个人账户结算审核失败，调用汇付商户入驻接口失败，hfId为空，respDesc：{}", hfBusinessEnterApplyResult.getRespDesc());
                        Throw.isBusinessException(hfBusinessEnterApplyResult.getRespDesc());
                    }
                } else if (settlementType == 2) {
                    // 提交商家入驻信息给汇付，如果调用接口失败，如果不是处理成功，则提示审核异常，请联系客服，并记录对应的hf原因，否则提示hf对应的错误信息
                    BeanUtils.copyProperties(tbMerchantEnterApplyPo, hfBusinessEnterApply);
                    hfBusinessEnterApply.setBusinessName(tbMerchantEnterApplyPo.getMerchantName());
                    hfBusinessEnterApply.setBusinessShortName(tbMerchantEnterApplyPo.getMerchantShortName());
                    // 入驻角色类型：1-商家，2-商户
                    hfBusinessEnterApply.setEnterType(2);
                    hfBusinessEnterApplyResult = hfApi.merchantEnt(hfBusinessEnterApply).unpack();
                    if (StringUtils.isBlank(hfBusinessEnterApplyResult.getHuiFuId())) {
                        log.error("商户对公账户结算审核失败，调用汇付商家入驻接口失败，hfId为空，respDesc：{}", hfBusinessEnterApplyResult.getRespDesc());
                        Throw.isBusinessException(hfBusinessEnterApplyResult.getRespDesc());
                    }
                }

                if (hfBusinessEnterApplyResult == null) {
                    log.error("商户审核失败，调用汇付商家入驻接口失败，hfBusinessEnterApplyResult为空");
                    Throw.isBusinessException("审核失败，请联系客服");
                }

                // 如果不为空，表示审核中，如果为空，表示基本信息入驻成功
                String applyNo = hfBusinessEnterApplyResult.getApplyNo();
                if (StringUtils.isBlank(applyNo)) {
                    // 审核成功，更新审核状态=审核成功，系统审核状态=汇付基本信息入驻审核成功 和 取现卡序列号
                    tbMerchantEnterApplyPo.setAuditState(AuditStateEnum.SUCCESS.getValue());
                    tbMerchantEnterApplyPo.setSystemAuditState(SystemAuditStateEnum.HF_ENTER_AUDIT_SUCCESS.getValue());
                } else {
                    tbMerchantEnterApplyPo.setSystemAuditState(SystemAuditStateEnum.HF_ENTER_WAIT_AUDIT.getValue());
                    tbMerchantEnterApplyPo.setHfApplyNo(applyNo);
                }

                tbMerchantEnterApplyPo.setHfMerchantNo(hfBusinessEnterApplyResult.getHuiFuId());
                tbMerchantEnterApplyPo.setWithdrawalCardNo(hfBusinessEnterApplyResult.getTokenNo());
            }
//            }
        }

        tbMerchantEnterApplyPo.setAuditTime(now);
        tbMerchantEnterApplyPo.setUpdateTime(now);
        int update = baseMapper.updateById(tbMerchantEnterApplyPo);
        if (update == 0) {
            Throw.isBusinessException("审核入驻记录失败");
        }

        if (AuditStateEnum.SUCCESS.getValue().equals(tbMerchantEnterApplyPo.getAuditState())) {
            merchantEnterMsgProvider.sendMsg(tbMerchantEnterApplyPo.getId());
        }

        if (AuditStateEnum.FAIL.getValue().equals(tbMerchantEnterApplyPo.getAuditState())) {
            // 审核拒绝，发送入驻失败短信
            smsBiz.sendEnterFailSms(tbMerchantEnterApplyPo.getMerchantName(), tbMerchantEnterApplyPo.getMobile());
        }

        return true;
    }

    @Override
    public Boolean enterSuccess(Long id) {
        TbMerchantEnterApplyPo tbMerchantEnterApplyPo = baseMapper.selectById(id);
        if (tbMerchantEnterApplyPo == null) {
            Throw.isBusinessException("未找到商户入驻申请数据");
        }

        // 商户入驻审核成功之后，需要新增商户账号数据，并关联，如果商户账号已经存在，则直接关联
        if (AuditStateEnum.SUCCESS.getValue().equals(tbMerchantEnterApplyPo.getAuditState())) {
            List<TbBusinessPo> tbBusinessPos = businessMapper.selectList(new QueryWrapper<TbBusinessPo>().eq("del_state", 0)
                    .eq("invite_code", tbMerchantEnterApplyPo.getSettleCode()));
            TbBusinessPo tbBusinessPo = tbBusinessPos.get(0);
            Long businessId = tbBusinessPo.getId();
            String openid = tbMerchantEnterApplyPo.getOpenid();
            LocalDateTime now = LocalDateUtil.getNowLocalDateTime();
            Long merchantId = null;
            TbMerchantPo tbMerchantPo = null;
            // 查询是否存在商户
            List<TbMerchantPo> tbMerchantPos = merchantMapper.selectList(new QueryWrapper<TbMerchantPo>().eq("openid", openid)
                    .orderByDesc("create_time"));

            List<TbBusinessMerchantPo> tbBusinessMerchantPos = new ArrayList<>();
            if (!CollectionUtils.isEmpty(tbMerchantPos)) {
                tbMerchantPo = tbMerchantPos.get(0);
                tbBusinessMerchantPos = businessMerchantMapper.selectList(new QueryWrapper<TbBusinessMerchantPo>()
                        .eq("business_id", businessId)
                        .eq("merchant_id", tbMerchantPo.getId()));
            }

            boolean sendMsg = false;
            TransactionStatus transaction = transactionManager.getTransaction(new DefaultTransactionAttribute());

            try {
                if (!CollectionUtils.isEmpty(tbMerchantPos)) {
                    // 如果已经存在商户，只需要商家和商户的关系绑定下
                    tbMerchantPo = tbMerchantPos.get(0);
                } else {
                    // 新增商户账号tb_merchant
                    tbMerchantPo = new TbMerchantPo();
                    BeanUtils.copyProperties(tbMerchantEnterApplyPo, tbMerchantPo);
                    tbMerchantPo.setMerchantNo(NoUtils.getMerchantNo());
                    tbMerchantPo.setOpenid(openid);
                    tbMerchantPo.setAvatar(tbMerchantEnterApplyPo.getLogo());
                    tbMerchantPo.setNickName(tbMerchantEnterApplyPo.getMerchantShortName());
                    tbMerchantPo.setProvinceName(tbMerchantEnterApplyPo.getBusinessProvinceName());
                    tbMerchantPo.setCityName(tbMerchantEnterApplyPo.getBusinessCityName());
                    tbMerchantPo.setCountyName(tbMerchantEnterApplyPo.getBusinessCountyName());
                    tbMerchantPo.setPosition(tbMerchantEnterApplyPo.getBusinessAddress());
                    // 状态(1-正常，2-已封禁)
                    tbMerchantPo.setState(1);
                    tbMerchantPo.setBalanceAmt(BigDecimal.ZERO);
                    tbMerchantPo.setFreezeAmt(BigDecimal.ZERO);
                    tbMerchantPo.setSubsidyAmt(BigDecimal.ZERO);
                    tbMerchantPo.setFreezeSubsidyAmt(BigDecimal.ZERO);
                    tbMerchantPo.setCreateTime(now);
                    int count = merchantMapper.insert(tbMerchantPo);
                    if (count == 0) {
                        log.error("新增商户账号失败");
                        Throw.isBusinessException("新增商户账号失败");
                    }
                    sendMsg = true;
                }
                merchantId = tbMerchantPo.getId();

                // 新增关联tb_business_merchant
                if (CollectionUtils.isEmpty(tbBusinessMerchantPos)) {
                    TbBusinessMerchantPo tbBusinessMerchantPo = new TbBusinessMerchantPo();
                    tbBusinessMerchantPo.setMerchantId(merchantId);
                    tbBusinessMerchantPo.setBusinessId(businessId);
                    tbBusinessMerchantPo.setTotalOrderAmt(BigDecimal.ZERO);
                    tbBusinessMerchantPo.setTotalOrderCount(0);
                    tbBusinessMerchantPo.setOwnState(OwnStateEnum.NO.getValue());
                    tbBusinessMerchantPo.setCreateTime(now);
                    int count = businessMerchantMapper.insert(tbBusinessMerchantPo);
                    if (count == 0) {
                        log.error("新增商户商家关联数据失败");
                        Throw.isBusinessException("新增商户商家关联数据失败");
                    }
                }

                transactionManager.commit(transaction);
            } catch (Exception e) {
                //回滚事务
                transactionManager.rollback(transaction);
                log.error("<商户入驻成功处理商户账号和绑定>事务异常回滚", e);
                Throw.isBusinessException(e.getMessage());
            }

            // 发送商户入驻成功的短信
            if (sendMsg) {
                Boolean sendState = smsBiz.sendEnterSuccessSms(tbMerchantEnterApplyPo.getMerchantShortName(), tbMerchantEnterApplyPo.getMobile());
                if (!sendState) {
                    log.error("发送商户入驻成功的短信失败，mobile：{}", tbBusinessPo.getMobile());
                }
            }
        }

        return true;
    }

    @Override
    public Boolean apply(MerchantEnterApplyDto merchantEnterApplyDto) {
        String openid = merchantEnterApplyDto.getOpenid();
        if (StringUtils.isBlank(openid)) {
            Throw.isBusinessException("请先授权");
        }

        String settleCode = merchantEnterApplyDto.getSettleCode();
        if (StringUtils.isBlank(settleCode)) {
            Throw.isBusinessException("入驻邀请码不能为空");
        }

//        String loginPass = merchantEnterApplyDto.getLoginPass();
//        if (StringUtils.isBlank(loginPass)) {
//            Throw.isBusinessException("商户密码不能为空");
//        }

        String mobile = merchantEnterApplyDto.getMobile();
        if (StringUtils.isBlank(mobile)) {
            Throw.isBusinessException("手机号不能为空");
        }

        // 对入驻的手机号加锁
        String lockKey = MessageFormat.format(Constant.LOCK_FORMAT, "merchantEnterApply:" + mobile);
        try {
            LockUtils.blockLock(lockKey, Constant.AUTO_UNLOCK_SECOND);

            // 校验入驻信息是否正确
            // 账户结算类型(1-个人账户结算，2-对公账户结算)
            Integer settlementType = merchantEnterApplyDto.getSettlementType();
            if (settlementType == null || settlementType == 1) {
                validEnterApplyInfo(merchantEnterApplyDto);
            } else {
                validBusinessEnterApplyInfo(merchantEnterApplyDto);
            }

            // 商家简称唯一
            Integer merchantShortNameCount = merchantMapper.selectCount(new QueryWrapper<TbMerchantPo>()
                    .eq("merchant_short_name", merchantEnterApplyDto.getMerchantShortName()));
            if (merchantShortNameCount != null && merchantShortNameCount > 0) {
                Throw.isBusinessException("商户简称已存在");
            }

            List<TbBusinessPo> tbBusinessPos = businessMapper.selectList(new QueryWrapper<TbBusinessPo>().eq("del_state", 0)
                    .eq("state", 1).eq("invite_code", settleCode));
            if (CollectionUtils.isEmpty(tbBusinessPos)) {
                Throw.isBusinessException(ResponseEnums.BUSINESS_INVITATION_URL_FAILED);
            }

            TbBusinessPo tbBusinessPo = tbBusinessPos.get(0);

            // 每个手机号只能存在一条待审核的入驻记录
//        Integer applyCount = baseMapper.selectCount(new QueryWrapper<TbMerchantEnterApplyPo>().eq("del_state", 0)
//                .eq("mobile", merchantEnterApplyDto.getMobile()).eq("audit_state", AuditStateEnum.WAIT_AUDIT.getValue()));
//        if (applyCount != null && applyCount > 0) {
//            Throw.isBusinessException("您已提交入驻申请，正在审核中");
//        }

            // 每个手机号只能存在一条商户数据
            Integer merchantCount = merchantMapper.selectCount(new QueryWrapper<TbMerchantPo>()
                    .eq("mobile", mobile));
            if (merchantCount != null && merchantCount > 0) {
                Throw.isBusinessException("手机号已被使用，请更换手机号");
            }

            // 判断是否存在手机号待审核or审核成功的申请商家入驻记录
            List<TbBusinessEnterApplyPo> tbBusinessEnterApplyPos = businessEnterApplyMapper.selectList(new QueryWrapper<TbBusinessEnterApplyPo>().eq("del_state", 0)
                    .eq("mobile", mobile)
                    .in("audit_state", Arrays.asList(AuditStateEnum.WAIT_AUDIT.getValue(), AuditStateEnum.WAIT_AUTH.getValue(), AuditStateEnum.SUCCESS.getValue())));
            if (!CollectionUtils.isEmpty(tbBusinessEnterApplyPos)) {
                Throw.isBusinessException("手机号已被使用，请更换手机号");
            }

            // 判断是否存在手机号待审核or审核成功的申请商户入驻记录
            List<TbMerchantEnterApplyPo> merchantEnterApplyPos = baseMapper.selectList(new QueryWrapper<TbMerchantEnterApplyPo>().eq("del_state", 0)
                    .eq("mobile", mobile)
                    .in("audit_state", Arrays.asList(AuditStateEnum.WAIT_AUDIT.getValue(), AuditStateEnum.SUCCESS.getValue())));
            if (!CollectionUtils.isEmpty(merchantEnterApplyPos)) {
                List<TbMerchantEnterApplyPo> waitMerchantEnterApplyList = merchantEnterApplyPos.stream()
                        .filter(merchantEnterApplyPo -> AuditStateEnum.WAIT_AUDIT.getValue().equals(merchantEnterApplyPo.getAuditState())).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(waitMerchantEnterApplyList)) {
                    for (TbMerchantEnterApplyPo tbMerchantEnterApplyPo : waitMerchantEnterApplyList) {
                        // 不是同个链接下的同个手机号申请入驻
                        if (!settleCode.equals(tbMerchantEnterApplyPo.getSettleCode())) {
                            Throw.isBusinessException("手机号已被使用，请更换手机号");
                        }
                    }

                    Throw.isBusinessException("你已提交入驻申请，正在审核中");
                }

                List<TbMerchantEnterApplyPo> successMerchantEnterApplyList = merchantEnterApplyPos.stream()
                        .filter(merchantEnterApplyPo -> AuditStateEnum.SUCCESS.getValue().equals(merchantEnterApplyPo.getAuditState())).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(successMerchantEnterApplyList)) {
                    Throw.isBusinessException("手机号已被使用，请更换手机号");
                }
            }

            // 每个用户只能存在一条待审核or审核成功的入驻记录
            List<TbMerchantEnterApplyPo> tbMerchantEnterApplyPos = baseMapper.selectList(new QueryWrapper<TbMerchantEnterApplyPo>()
                    .eq("del_state", 0)
                    .eq("openid", openid)
                    .orderByDesc("apply_time"));
            if (!CollectionUtils.isEmpty(tbMerchantEnterApplyPos)) {
                TbMerchantEnterApplyPo tbMerchantEnterApplyPo = tbMerchantEnterApplyPos.get(0);
                Integer auditState = tbMerchantEnterApplyPo.getAuditState();
                if (AuditStateEnum.WAIT_AUDIT.getValue().equals(auditState)) {
                    Throw.isBusinessException("你已提交入驻申请，正在审核中");
                }

                if (AuditStateEnum.WAIT_AUTH.getValue().equals(auditState)) {
                    Throw.isBusinessException("你已提交入驻申请，请进行签约认证");
                }

//            if (AuditStateEnum.FAIL.getValue().equals(auditState)) {
//                Throw.isBusinessException("入驻审核拒绝，请重新申请");
//            }

                if (AuditStateEnum.SUCCESS.getValue().equals(auditState)) {
                    Throw.isBusinessException("入驻审核成功，请登录");
                }
            }

//        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
//        String encodedPassword = encoder.encode(loginPass);

            TbMerchantEnterApplyPo tbMerchantEnterApplyPo = new TbMerchantEnterApplyPo();
            BeanUtils.copyProperties(merchantEnterApplyDto, tbMerchantEnterApplyPo);
            tbMerchantEnterApplyPo.setOpenid(openid);
//        tbMerchantEnterApplyPo.setLoginPass(encodedPassword);
            tbMerchantEnterApplyPo.setApplyNo(NoUtils.getMerchantEnterApplyNo());
            tbMerchantEnterApplyPo.setApplyIp(merchantEnterApplyDto.getApplyIp());
            tbMerchantEnterApplyPo.setAuditState(AuditStateEnum.WAIT_AUDIT.getValue());
            tbMerchantEnterApplyPo.setSystemAuditState(SystemAuditStateEnum.MANAGER_WAIT_AUDIT.getValue());
            tbMerchantEnterApplyPo.setApplyTime(LocalDateTime.now());
            tbMerchantEnterApplyPo.setCreateTime(LocalDateTime.now());
            int insert = baseMapper.insert(tbMerchantEnterApplyPo);
            if (insert == 0) {
                Throw.isBusinessException("商户入驻申请失败");
            }

            // 发送商户入驻申请系统通知
            NotifyMsgSendDto notifyMsgSendDto = new NotifyMsgSendDto();
            notifyMsgSendDto.setUserId(tbBusinessPo.getUserId());
            notifyMsgSendDto.setRoleType(RoleTypeEnum.BUSINESS.getValue());
            notifyMsgSendDto.setMsgType(NotifyMsgTypeEnum.BUSINESS_MERCHANT_ENTER_APPLY.getValue());
            notifyMsgSendDto.setContent(String.format(MsgConstant.BUSINESS_MERCHANT_ENTER_APPLY, tbMerchantEnterApplyPo.getMerchantName()));
            notifyMsgSendDto.setMsgState(NotifyMsgStateEnum.NO_READ.getValue());
            notifyMsgProvider.sendMsg(notifyMsgSendDto);

            return true;
        } finally {
            LockUtils.unlock(lockKey);
        }
    }

    private void validBusinessEnterApplyInfo(MerchantEnterApplyDto merchantEnterApplyDto) {
        String merchantName = merchantEnterApplyDto.getMerchantName();
        if (StringUtils.isBlank(merchantName)) {
            Throw.isBusinessException("请输入商户名称");
        }

        String merchantShortName = merchantEnterApplyDto.getMerchantShortName();
        if (StringUtils.isBlank(merchantShortName)) {
            Throw.isBusinessException("请输入商户简称");
        }

        Integer companyType = merchantEnterApplyDto.getCompanyType();
        if (companyType == null || CompanyTypeEnum.typeOf(companyType) == null) {
            Throw.isBusinessException("请选择公司类型");
        }

        String logo = merchantEnterApplyDto.getLogo();
        if (StringUtils.isBlank(logo)) {
            Throw.isBusinessException("请上传商户logo");
        }

        Long mccOneId = merchantEnterApplyDto.getMccOneId();
        Long mccTwoId = merchantEnterApplyDto.getMccTwoId();
        String mcc = merchantEnterApplyDto.getMcc();
        String mccName = merchantEnterApplyDto.getMccName();
        if (mccOneId == null || mccTwoId == null && StringUtils.isBlank(mcc) || StringUtils.isBlank(mccName)) {
            Throw.isBusinessException("请选择所属行业");
        }

        if (StringUtils.isBlank(merchantEnterApplyDto.getLicensePic()) || StringUtils.isBlank(merchantEnterApplyDto.getLicensePicUrl())) {
            Throw.isBusinessException("请上传营业执照");
        }

        Integer licenseValidityType = merchantEnterApplyDto.getLicenseValidityType();
        if (licenseValidityType == null || CertValidityTypeEnum.typeOfValue(licenseValidityType) == null) {
            Throw.isBusinessException("请选择营业执照有效期");
        }

        if (CertValidityTypeEnum.NO.getValue().equals(licenseValidityType)) {
            String licenseBeginDate = merchantEnterApplyDto.getLicenseBeginDate();
            String licenseEndDate = merchantEnterApplyDto.getLicenseEndDate();
            if (StringUtils.isBlank(licenseBeginDate)) {
                Throw.isBusinessException("请选择营业执照有效期开始日期");
            }

            if (StringUtils.isBlank(licenseEndDate)) {
                Throw.isBusinessException("请选择营业执照有效期截止日期");
            }

            LocalDate licenseBeginLocalDate = null;
            LocalDate licenseEndLocalDate = null;
            try {
                licenseBeginLocalDate = LocalDateUtil.toLocalDate(licenseBeginDate, Constant.YYYY_MM_DD);
            } catch (Exception e) {
                Throw.isBusinessException("营业执照有效期开始日期选择错误");
            }

            try {
                licenseEndLocalDate = LocalDateUtil.toLocalDate(licenseEndDate, Constant.YYYY_MM_DD);
            } catch (Exception e) {
                Throw.isBusinessException("营业执照有效期截止日期选择错误");
            }

            if (licenseEndLocalDate.compareTo(licenseBeginLocalDate) <= 0) {
                Throw.isBusinessException("营业执照有效期截止日期必须大于开始日期");
            }
        } else {
            // 如果是长期有效，营业执照有效期开始日期也不能为空
            String licenseBeginDate = merchantEnterApplyDto.getLicenseBeginDate();
            if (StringUtils.isBlank(licenseBeginDate)) {
                Throw.isBusinessException("请选择营业执照有效期开始日期");
            }

            LocalDate licenseBeginLocalDate = null;
            try {
                licenseBeginLocalDate = LocalDateUtil.toLocalDate(licenseBeginDate, Constant.YYYY_MM_DD);
            } catch (Exception e) {
                Throw.isBusinessException("营业执照有效期开始日期选择错误");
            }
        }

        String foundDate = merchantEnterApplyDto.getFoundDate();
        if (StringUtils.isBlank(foundDate)) {
            Throw.isBusinessException("请选择成立时间");
        }

        try {
            LocalDateUtil.toLocalDate(foundDate, Constant.YYYY_MM_DD);
        } catch (Exception e) {
            Throw.isBusinessException("成立时间选择错误");
        }

        // 保留两位小数；条件选填，国营企业、私营企业、外资企业、事业单位、其他、集体经济必填，政府机构、个体工商户可为空
        BigDecimal regCapital = merchantEnterApplyDto.getRegCapital();
        if (!CompanyTypeEnum.GTGSH.getValue().equals(companyType) && !CompanyTypeEnum.ZFJG.getValue().equals(companyType)) {
            if (regCapital == null || regCapital.compareTo(BigDecimal.ZERO) <= 0) {
                Throw.isBusinessException("请输入注册资本");
            }
        }

        String businessScope = merchantEnterApplyDto.getBusinessScope();
        if (StringUtils.isBlank(businessScope)) {
            Throw.isBusinessException("请输入经营范围");
        }

        String regProvinceName = merchantEnterApplyDto.getRegProvinceName();
        String regProvinceCode = merchantEnterApplyDto.getRegProvinceCode();
        String regCityName = merchantEnterApplyDto.getRegCityName();
        String regCityCode = merchantEnterApplyDto.getRegCityCode();
        String regCountyName = merchantEnterApplyDto.getRegCountyName();
        String regCountyCode = merchantEnterApplyDto.getRegCountyCode();
        if (StringUtils.isBlank(regProvinceName) || StringUtils.isBlank(regProvinceCode)) {
            Throw.isBusinessException("请选择注册省份");
        }

        if (StringUtils.isBlank(regCityName) || StringUtils.isBlank(regCityCode)) {
            Throw.isBusinessException("请选择注册市");
        }

        if (StringUtils.isBlank(regCountyName) || StringUtils.isBlank(regCountyCode)) {
            Throw.isBusinessException("请选择注册区县");
        }

        String regAddress = merchantEnterApplyDto.getRegAddress();
        if (StringUtils.isBlank(regAddress)) {
            Throw.isBusinessException("请输入注册详细地址");
        }

        String businessProvinceName = merchantEnterApplyDto.getBusinessProvinceName();
        String businessProvinceCode = merchantEnterApplyDto.getBusinessProvinceCode();
        String businessCityName = merchantEnterApplyDto.getBusinessCityName();
        String businessCityCode = merchantEnterApplyDto.getBusinessCityCode();
        String businessCountyName = merchantEnterApplyDto.getBusinessCountyName();
        String businessCountyCode = merchantEnterApplyDto.getBusinessCountyCode();

        if (StringUtils.isBlank(businessProvinceName) || StringUtils.isBlank(businessProvinceCode)) {
            Throw.isBusinessException("请选择经营省份");
        }

        if (StringUtils.isBlank(businessCityName) || StringUtils.isBlank(businessCityCode)) {
            Throw.isBusinessException("请选择经营市");
        }

        if (StringUtils.isBlank(businessCountyName) || StringUtils.isBlank(businessCountyCode)) {
            Throw.isBusinessException("请选择经营区县");
        }

        String businessAddress = merchantEnterApplyDto.getBusinessAddress();
        if (StringUtils.isBlank(businessAddress)) {
            Throw.isBusinessException("请输入经营详细地址");
        }

        String customerMobile = merchantEnterApplyDto.getCustomerMobile();
        if (StringUtils.isBlank(customerMobile)) {
            Throw.isBusinessException("请输入客服电话");
        }

        String contactName = merchantEnterApplyDto.getContactName();
        if (StringUtils.isBlank(contactName)) {
            Throw.isBusinessException("请输入联系人姓名");
        }

        String contactMobileNo = merchantEnterApplyDto.getContactMobileNo();
        if (StringUtils.isBlank(contactMobileNo)) {
            Throw.isBusinessException("请输入联系人手机号");
        }

        String contactEmail = merchantEnterApplyDto.getContactEmail();
        if (StringUtils.isBlank(contactEmail)) {
            Throw.isBusinessException("请输入联系人电子邮箱");
        }

        String contactCertNo = merchantEnterApplyDto.getContactCertNo();
        if (StringUtils.isBlank(contactCertNo)) {
            Throw.isBusinessException("请输入联系人身份证号");
        }

        if (StringUtils.isBlank(merchantEnterApplyDto.getStoreHeaderPic()) || StringUtils.isBlank(merchantEnterApplyDto.getStoreHeaderPicUrl())) {
            Throw.isBusinessException("请上传线下经营-门头照");
        }

        if (StringUtils.isBlank(merchantEnterApplyDto.getStoreIndoorPic()) || StringUtils.isBlank(merchantEnterApplyDto.getStoreIndoorPicUrl())) {
            Throw.isBusinessException("请上传线下经营-内景照");
        }

        if (StringUtils.isBlank(merchantEnterApplyDto.getStoreCashierDeskPic()) || StringUtils.isBlank(merchantEnterApplyDto.getStoreCashierDeskPicUrl())) {
            Throw.isBusinessException("请上传线下经营-收银台");
        }

        String legalName = merchantEnterApplyDto.getLegalName();
        if (StringUtils.isBlank(legalName)) {
            Throw.isBusinessException("请输入法人姓名");
        }

        String legalCertType = merchantEnterApplyDto.getLegalCertType();
        if (StringUtils.isBlank(legalCertType) || CertTypeEnum.typeOfValue(legalCertType) == null) {
            Throw.isBusinessException("请输入法人证件类型");
        }

        String legalCertNo = merchantEnterApplyDto.getLegalCertNo();
        if (StringUtils.isBlank(legalCertNo)) {
            Throw.isBusinessException("请输入法人证件号码");
        }

        Integer legalCertValidityType = merchantEnterApplyDto.getLegalCertValidityType();
        if (legalCertValidityType == null || CertValidityTypeEnum.typeOfValue(legalCertValidityType) == null) {
            Throw.isBusinessException("请选择法人证件有效期");
        }

        if (CertValidityTypeEnum.NO.getValue().equals(legalCertValidityType)) {
            String legalCertBeginDate = merchantEnterApplyDto.getLegalCertBeginDate();
            String legalCertEndDate = merchantEnterApplyDto.getLegalCertEndDate();
            if (StringUtils.isBlank(legalCertBeginDate)) {
                Throw.isBusinessException("请选择法人证件有效期开始日期");
            }

            if (StringUtils.isBlank(legalCertEndDate)) {
                Throw.isBusinessException("请选择法人证件有效期截止日期");
            }

            LocalDate legalCertBeginLocalDate = null;
            LocalDate legalCertEndLocalDate = null;
            try {
                legalCertBeginLocalDate = LocalDateUtil.toLocalDate(legalCertBeginDate, Constant.YYYY_MM_DD);
            } catch (Exception e) {
                Throw.isBusinessException("法人证件有效期开始日期选择错误");
            }

            try {
                legalCertEndLocalDate = LocalDateUtil.toLocalDate(legalCertEndDate, Constant.YYYY_MM_DD);
            } catch (Exception e) {
                Throw.isBusinessException("法人证件有效期截止日期选择错误");
            }

            if (legalCertEndLocalDate.compareTo(legalCertBeginLocalDate) <= 0) {
                Throw.isBusinessException("法人证件有效期截止日期必须大于开始日期");
            }
        } else {
            // 如果是长期有效，法人证件有效期开始日期也不能为空
            String legalCertBeginDate = merchantEnterApplyDto.getLegalCertBeginDate();
            if (StringUtils.isBlank(legalCertBeginDate)) {
                Throw.isBusinessException("请选择法人证件有效期开始日期");
            }

            LocalDate legalCertBeginLocalDate = null;
            try {
                legalCertBeginLocalDate = LocalDateUtil.toLocalDate(legalCertBeginDate, Constant.YYYY_MM_DD);
            } catch (Exception e) {
                Throw.isBusinessException("法人证件有效期开始日期选择错误");
            }
        }

        String legalMobileNo = merchantEnterApplyDto.getLegalMobileNo();
        if (StringUtils.isBlank(legalMobileNo)) {
            Throw.isBusinessException("请输入法人手机号");
        }

        String legalAddr = merchantEnterApplyDto.getLegalAddr();
        if (StringUtils.isBlank(legalAddr)) {
            Throw.isBusinessException("请输入法人身份证地址");
        }

        if (StringUtils.isBlank(merchantEnterApplyDto.getLegalCertFrontPic()) || StringUtils.isBlank(merchantEnterApplyDto.getLegalCertFrontPicUrl())) {
            Throw.isBusinessException("请上传法人身份证人像面");
        }

        if (StringUtils.isBlank(merchantEnterApplyDto.getLegalCertBackPic()) || StringUtils.isBlank(merchantEnterApplyDto.getLegalCertBackPicUrl())) {
            Throw.isBusinessException("请上传法人身份证国徽面");
        }

//        Integer signUserType = merchantEnterApplyDto.getSignUserType();
//        if (signUserType == null || SignUserTypeEnum.typeOfValue(signUserType) == null) {
//            Throw.isBusinessException("请选择签约人");
//        }
//
//        String contactCertNo = merchantEnterApplyDto.getContactCertNo();
//        if (SignUserTypeEnum.CONTACT.getValue().equals(signUserType) && StringUtils.isBlank(contactCertNo)) {
//            Throw.isBusinessException("请填写联系人身份证号");
//        }

        Integer cardType = merchantEnterApplyDto.getCardType();
        if (cardType == null || CardTypeEnum.typeOfValue(cardType) == null) {
            Throw.isBusinessException("请选择账户类型");
        }

        if (CardTypeEnum.DG.getValue().equals(cardType)) {
            // 对公账户
            if (StringUtils.isBlank(merchantEnterApplyDto.getRegAcctPic()) || StringUtils.isBlank(merchantEnterApplyDto.getRegAcctPicUrl())) {
                Throw.isBusinessException("请上传开户许可证");
            }

            // 当注册地址或经营地址为如下地区时必填：浙江,海南,重庆,河南,江苏,宁波市,黑龙江,吉林,湖南,贵州,陕西,湖北
            // 当注册地址或经营地址为如下地区时必填：江苏省、浙江省、湖南省、湖北省、云南省、贵州省、陕西省、河南省、吉林省、黑龙江省、福建省、海南省、重庆市、青海省、宁夏回族自治区；
//            if (businessProvinceName.contains("江苏") || businessProvinceName.contains("浙江") || businessProvinceName.contains("湖南")
//                    || businessProvinceName.contains("湖北") || businessProvinceName.contains("云南") || businessProvinceName.contains("贵州")
//                    || businessProvinceName.contains("陕西") || businessProvinceName.contains("河南") || businessProvinceName.contains("吉林")
//                    || businessProvinceName.contains("黑龙江") || businessProvinceName.contains("福建") || businessProvinceName.contains("海南")
//                    || businessProvinceName.contains("重庆") || businessProvinceName.contains("青海") || businessProvinceName.contains("宁夏")) {
            String openLicenceNo = merchantEnterApplyDto.getOpenLicenceNo();
            if (StringUtils.isBlank(openLicenceNo)) {
                Throw.isBusinessException("请填写开户许可证核准号");
            }
//            }

            String branchCode = merchantEnterApplyDto.getBranchCode();
            if (StringUtils.isBlank(branchCode)) {
                Throw.isBusinessException("请填写联行号");
            }

            // 银行编号
//            String bankCode = merchantEnterApplyDto.getBankCode();
//            if (StringUtils.isBlank(bankCode)) {
//                Throw.isBusinessException("请选择银行");
//            }
//
//            // 支行名称
//            String branchName = merchantEnterApplyDto.getBranchName();
//            if (StringUtils.isBlank(branchName)) {
//                Throw.isBusinessException("请填写开户支行名称");
//            }
        } else if (CardTypeEnum.DS.getValue().equals(cardType)) {
            // 对私法人账户
            String certType = merchantEnterApplyDto.getCertType();
            if (certType == null || CertTypeEnum.typeOfValue(certType) == null) {
                Throw.isBusinessException("请选择持卡人证件类型");
            }

            String certNo = merchantEnterApplyDto.getCertNo();
            if (StringUtils.isBlank(certNo)) {
                Throw.isBusinessException("请选择持卡人证件号码");
            }

            Integer certValidityType = merchantEnterApplyDto.getCertValidityType();
            if (certValidityType == null || CertValidityTypeEnum.typeOfValue(certValidityType) == null) {
                Throw.isBusinessException("请选择持卡人证件有效期");
            }

            if (CertValidityTypeEnum.NO.getValue().equals(certValidityType)) {
                String certBeginDate = merchantEnterApplyDto.getCertBeginDate();
                String certEndDate = merchantEnterApplyDto.getCertEndDate();
                if (StringUtils.isBlank(certBeginDate)) {
                    Throw.isBusinessException("请选择持卡人证件有效期开始日期");
                }

                if (StringUtils.isBlank(certEndDate)) {
                    Throw.isBusinessException("请选择持卡人证件有效期截止日期");
                }

                LocalDate certBeginLocalDate = null;
                LocalDate certEndLocalDate = null;
                try {
                    certBeginLocalDate = LocalDateUtil.toLocalDate(certBeginDate, Constant.YYYY_MM_DD);
                } catch (Exception e) {
                    Throw.isBusinessException("持卡人证件有效期开始日期选择错误");
                }

                try {
                    certEndLocalDate = LocalDateUtil.toLocalDate(certEndDate, Constant.YYYY_MM_DD);
                } catch (Exception e) {
                    Throw.isBusinessException("持卡人证件有效期截止日期选择错误");
                }

                if (certEndLocalDate.compareTo(certBeginLocalDate) <= 0) {
                    Throw.isBusinessException("持卡人证件有效期截止日期必须大于开始日期");
                }
            }


            if (StringUtils.isBlank(merchantEnterApplyDto.getSettleCardFrontPic()) || StringUtils.isBlank(merchantEnterApplyDto.getSettleCardFrontPicUrl())) {
                Throw.isBusinessException("请上传银行卡正面");
            }

            if (StringUtils.isBlank(merchantEnterApplyDto.getSettleCertFrontPic()) || StringUtils.isBlank(merchantEnterApplyDto.getSettleCertFrontPicUrl())) {
                Throw.isBusinessException("请上传持卡人身份证人像面");
            }

            if (StringUtils.isBlank(merchantEnterApplyDto.getSettleCertBackPic()) || StringUtils.isBlank(merchantEnterApplyDto.getSettleCertBackPicUrl())) {
                Throw.isBusinessException("请上传持卡人身份证国徽面");
            }

            String mp = merchantEnterApplyDto.getMp();
            if (StringUtils.isBlank(mp)) {
                Throw.isBusinessException("请输入银行卡绑定手机号");
            }
        }

        String cardName = merchantEnterApplyDto.getCardName();
        if (StringUtils.isBlank(cardName)) {
            Throw.isBusinessException("请输入账户名称");
        }

        String cardNo = merchantEnterApplyDto.getCardNo();
        if (StringUtils.isBlank(cardNo)) {
            Throw.isBusinessException("请输入银行账号");
        }

        String bankCode = merchantEnterApplyDto.getBankCode();
        if (StringUtils.isBlank(bankCode)) {
            Throw.isBusinessException("请选择所属银行");
        }

        HfBankIdEnum hfBankIdEnum = HfBankIdEnum.typeOfValue(bankCode);
        if (hfBankIdEnum == null) {
            Throw.isBusinessException("所属银行不支持");
        }

        String bankProvinceName = merchantEnterApplyDto.getBankProvinceName();
        String bankProvinceCode = merchantEnterApplyDto.getBankProvinceCode();
        String bankCityName = merchantEnterApplyDto.getBankCityName();
        String bankCityCode = merchantEnterApplyDto.getBankCityCode();
        String bankCountyName = merchantEnterApplyDto.getBankCountyName();
        String bankCountyCode = merchantEnterApplyDto.getBankCountyCode();
        if (StringUtils.isBlank(bankProvinceName) || StringUtils.isBlank(bankProvinceCode)) {
            Throw.isBusinessException("请选择银行卡所在地省份");
        }

        if (StringUtils.isBlank(bankCityName) || StringUtils.isBlank(bankCityCode)) {
            Throw.isBusinessException("请选择银行卡所在地市");
        }

        if (StringUtils.isBlank(bankCountyName) || StringUtils.isBlank(bankCountyCode)) {
            Throw.isBusinessException("请选择银行卡所在地区县");
        }
    }

    private void validEnterApplyInfo(MerchantEnterApplyDto merchantEnterApplyDto) {
        String businessName = merchantEnterApplyDto.getMerchantName();
        if (StringUtils.isBlank(businessName)) {
            Throw.isBusinessException("请输入商户名称");
        }

        String businessShortName = merchantEnterApplyDto.getMerchantShortName();
        if (StringUtils.isBlank(businessShortName)) {
            Throw.isBusinessException("请输入商户简称");
        }

        String logo = merchantEnterApplyDto.getLogo();
        if (StringUtils.isBlank(logo)) {
            Throw.isBusinessException("请上传商户logo");
        }

        Long mccOneId = merchantEnterApplyDto.getMccOneId();
        Long mccTwoId = merchantEnterApplyDto.getMccTwoId();
        String mcc = merchantEnterApplyDto.getMcc();
        String mccName = merchantEnterApplyDto.getMccName();
        if (mccOneId == null || mccTwoId == null || StringUtils.isBlank(mcc) || StringUtils.isBlank(mccName)) {
            Throw.isBusinessException("请选择所属行业");
        }

        String businessProvinceName = merchantEnterApplyDto.getBusinessProvinceName();
        String businessProvinceCode = merchantEnterApplyDto.getBusinessProvinceCode();
        String businessCityName = merchantEnterApplyDto.getBusinessCityName();
        String businessCityCode = merchantEnterApplyDto.getBusinessCityCode();
        String businessCountyName = merchantEnterApplyDto.getBusinessCountyName();
        String businessCountyCode = merchantEnterApplyDto.getBusinessCountyCode();

        if (StringUtils.isBlank(businessProvinceName) || StringUtils.isBlank(businessProvinceCode)) {
            Throw.isBusinessException("请选择经营省份");
        }

        if (StringUtils.isBlank(businessCityName) || StringUtils.isBlank(businessCityCode)) {
            Throw.isBusinessException("请选择经营市");
        }

        if (StringUtils.isBlank(businessCountyName) || StringUtils.isBlank(businessCountyCode)) {
            Throw.isBusinessException("请选择经营区县");
        }

        String businessAddress = merchantEnterApplyDto.getBusinessAddress();
        if (StringUtils.isBlank(businessAddress)) {
            Throw.isBusinessException("请输入经营详细地址");
        }

//        String customerMobile = merchantEnterApplyDto.getCustomerMobile();
//        if (StringUtils.isBlank(customerMobile)) {
//            Throw.isBusinessException("请输入客服电话");
//        }

        String contactName = merchantEnterApplyDto.getContactName();
        if (StringUtils.isBlank(contactName)) {
            Throw.isBusinessException("请输入联系人姓名");
        }

        String contactMobileNo = merchantEnterApplyDto.getContactMobileNo();
        if (StringUtils.isBlank(contactMobileNo)) {
            Throw.isBusinessException("请输入联系人手机号");
        }

        String contactEmail = merchantEnterApplyDto.getContactEmail();
        if (StringUtils.isBlank(contactEmail)) {
            Throw.isBusinessException("请输入联系人电子邮箱");
        }

        if (StringUtils.isBlank(merchantEnterApplyDto.getStoreHeaderPic()) || StringUtils.isBlank(merchantEnterApplyDto.getStoreHeaderPicUrl())) {
            Throw.isBusinessException("请上传线下经营-门头照");
        }

        if (StringUtils.isBlank(merchantEnterApplyDto.getStoreIndoorPic()) || StringUtils.isBlank(merchantEnterApplyDto.getStoreIndoorPicUrl())) {
            Throw.isBusinessException("请上传线下经营-内景照");
        }

        if (StringUtils.isBlank(merchantEnterApplyDto.getStoreCashierDeskPic()) || StringUtils.isBlank(merchantEnterApplyDto.getStoreCashierDeskPicUrl())) {
            Throw.isBusinessException("请上传线下经营-收银台");
        }

        // 只支持身份证号
        merchantEnterApplyDto.setLegalCertType(CertTypeEnum.SFZ.getValue());

        String legalMobileNo = merchantEnterApplyDto.getLegalMobileNo();
        if (StringUtils.isBlank(legalMobileNo)) {
            Throw.isBusinessException("请输入法人手机号");
        }

        String legalCertNo = merchantEnterApplyDto.getLegalCertNo();
        if (StringUtils.isBlank(legalCertNo)) {
            Throw.isBusinessException("请输入法人证件号码");
        }

        Integer legalCertValidityType = merchantEnterApplyDto.getLegalCertValidityType();
        if (legalCertValidityType == null || CertValidityTypeEnum.typeOfValue(legalCertValidityType) == null) {
            Throw.isBusinessException("请选择法人证件有效期");
        }

        if (CertValidityTypeEnum.NO.getValue().equals(legalCertValidityType)) {
            String legalCertBeginDate = merchantEnterApplyDto.getLegalCertBeginDate();
            String legalCertEndDate = merchantEnterApplyDto.getLegalCertEndDate();
            if (StringUtils.isBlank(legalCertBeginDate)) {
                Throw.isBusinessException("请选择法人证件有效期开始日期");
            }

            if (StringUtils.isBlank(legalCertEndDate)) {
                Throw.isBusinessException("请选择法人证件有效期截止日期");
            }

            LocalDate legalCertBeginLocalDate = null;
            LocalDate legalCertEndLocalDate = null;
            try {
                legalCertBeginLocalDate = LocalDateUtil.toLocalDate(legalCertBeginDate, Constant.YYYY_MM_DD);
            } catch (Exception e) {
                Throw.isBusinessException("法人证件有效期开始日期选择错误");
            }

            try {
                legalCertEndLocalDate = LocalDateUtil.toLocalDate(legalCertEndDate, Constant.YYYY_MM_DD);
            } catch (Exception e) {
                Throw.isBusinessException("法人证件有效期截止日期选择错误");
            }

            if (legalCertEndLocalDate.compareTo(legalCertBeginLocalDate) <= 0) {
                Throw.isBusinessException("法人证件有效期截止日期必须大于开始日期");
            }
        } else {
            // 如果是长期有效，法人证件有效期开始日期也不能为空
            String legalCertBeginDate = merchantEnterApplyDto.getLegalCertBeginDate();
            if (StringUtils.isBlank(legalCertBeginDate)) {
                Throw.isBusinessException("请选择法人证件有效期开始日期");
            }

            LocalDate legalCertBeginLocalDate = null;
            try {
                legalCertBeginLocalDate = LocalDateUtil.toLocalDate(legalCertBeginDate, Constant.YYYY_MM_DD);
            } catch (Exception e) {
                Throw.isBusinessException("法人证件有效期开始日期选择错误");
            }
        }

        String legalAddr = merchantEnterApplyDto.getLegalAddr();
        if (StringUtils.isBlank(legalAddr)) {
            Throw.isBusinessException("请输入法人身份证地址");
        }

        if (StringUtils.isBlank(merchantEnterApplyDto.getLegalCertFrontPic()) || StringUtils.isBlank(merchantEnterApplyDto.getLegalCertFrontPicUrl())) {
            Throw.isBusinessException("请上传法人身份证人像面");
        }

        if (StringUtils.isBlank(merchantEnterApplyDto.getLegalCertBackPic()) || StringUtils.isBlank(merchantEnterApplyDto.getLegalCertBackPicUrl())) {
            Throw.isBusinessException("请上传法人身份证国徽面");
        }


        // 对私法人账户
        String certType = merchantEnterApplyDto.getCertType();
        if (certType == null || CertTypeEnum.typeOfValue(certType) == null) {
            Throw.isBusinessException("请选择持卡人证件类型");
        }

        String certNo = merchantEnterApplyDto.getCertNo();
        if (StringUtils.isBlank(certNo)) {
            Throw.isBusinessException("请选择持卡人证件号码");
        }

        Integer certValidityType = merchantEnterApplyDto.getCertValidityType();
        if (certValidityType == null || CertValidityTypeEnum.typeOfValue(certValidityType) == null) {
            Throw.isBusinessException("请选择持卡人证件有效期");
        }

        String certBeginDate = merchantEnterApplyDto.getCertBeginDate();
        if (StringUtils.isBlank(certBeginDate)) {
            Throw.isBusinessException("请选择持卡人证件有效期开始日期");
        }

        if (CertValidityTypeEnum.NO.getValue().equals(certValidityType)) {
            String certEndDate = merchantEnterApplyDto.getCertEndDate();
            if (StringUtils.isBlank(certEndDate)) {
                Throw.isBusinessException("请选择持卡人证件有效期截止日期");
            }

            LocalDate certBeginLocalDate = null;
            LocalDate certEndLocalDate = null;
            try {
                certBeginLocalDate = LocalDateUtil.toLocalDate(certBeginDate, Constant.YYYY_MM_DD);
            } catch (Exception e) {
                Throw.isBusinessException("持卡人证件有效期开始日期选择错误");
            }

            try {
                certEndLocalDate = LocalDateUtil.toLocalDate(certEndDate, Constant.YYYY_MM_DD);
            } catch (Exception e) {
                Throw.isBusinessException("持卡人证件有效期截止日期选择错误");
            }

            if (certEndLocalDate.compareTo(certBeginLocalDate) <= 0) {
                Throw.isBusinessException("持卡人证件有效期截止日期必须大于开始日期");
            }

            if (StringUtils.isBlank(merchantEnterApplyDto.getSettleCardFrontPic()) || StringUtils.isBlank(merchantEnterApplyDto.getSettleCardFrontPicUrl())) {
                Throw.isBusinessException("请上传银行卡正面");
            }

            String mp = merchantEnterApplyDto.getMp();
            if (StringUtils.isBlank(mp)) {
                Throw.isBusinessException("请输入银行卡绑定手机号");
            }
        }

        String cardName = merchantEnterApplyDto.getCardName();
        if (StringUtils.isBlank(cardName)) {
            Throw.isBusinessException("请输入账户名称");
        }

        String cardNo = merchantEnterApplyDto.getCardNo();
        if (StringUtils.isBlank(cardNo)) {
            Throw.isBusinessException("请输入银行账号");
        }

        String bankCode = merchantEnterApplyDto.getBankCode();
        if (StringUtils.isBlank(bankCode)) {
            Throw.isBusinessException("请选择所属银行");
        }

        HfBankIdEnum hfBankIdEnum = HfBankIdEnum.typeOfValue(bankCode);
        if (hfBankIdEnum == null) {
            Throw.isBusinessException("所属银行不支持");
        }

        String bankProvinceName = merchantEnterApplyDto.getBankProvinceName();
        String bankProvinceCode = merchantEnterApplyDto.getBankProvinceCode();
        String bankCityName = merchantEnterApplyDto.getBankCityName();
        String bankCityCode = merchantEnterApplyDto.getBankCityCode();
        String bankCountyName = merchantEnterApplyDto.getBankCountyName();
        String bankCountyCode = merchantEnterApplyDto.getBankCountyCode();
        if (StringUtils.isBlank(bankProvinceName) || StringUtils.isBlank(bankProvinceCode)) {
            Throw.isBusinessException("请选择银行卡所在地省份");
        }

        if (StringUtils.isBlank(bankCityName) || StringUtils.isBlank(bankCityCode)) {
            Throw.isBusinessException("请选择银行卡所在地市");
        }

        if (StringUtils.isBlank(bankCountyName) || StringUtils.isBlank(bankCountyCode)) {
            Throw.isBusinessException("请选择银行卡所在地区县");
        }
    }

    @Override
    public PreApplyMerchantVo preApply(PreApplyMerchantDto preApplyMerchantDto) {
        String openid = preApplyMerchantDto.getOpenid();
        if (StringUtils.isBlank(openid)) {
            Throw.isBusinessException("请先授权");
        }

        String settleCode = preApplyMerchantDto.getSettleCode();
        if (StringUtils.isBlank(settleCode)) {
            Throw.isBusinessException("入驻邀请码不能为空");
        }

        List<TbBusinessPo> tbBusinessPos = businessMapper.selectList(new QueryWrapper<TbBusinessPo>().eq("del_state", 0)
                .eq("state", 1).eq("invite_code", settleCode));
        if (CollectionUtils.isEmpty(tbBusinessPos)) {
            Throw.isBusinessException(ResponseEnums.BUSINESS_INVITATION_URL_FAILED);
        }

        PreApplyMerchantVo preApplyMerchantVo = new PreApplyMerchantVo();
        // 入驻状态：0-未申请，1-待审核，2-审核失败，3-审核成功
        preApplyMerchantVo.setState(0);

        List<TbMerchantEnterApplyPo> tbMerchantEnterApplyPos = baseMapper.selectList(new QueryWrapper<TbMerchantEnterApplyPo>()
                .eq("del_state", 0)
//                .eq("settle_code", settleCode)
                .eq("openid", openid)
                .orderByDesc("apply_time"));
        if (!CollectionUtils.isEmpty(tbMerchantEnterApplyPos)) {
            // 根据申请时间，获取最近的一次申请记录
            TbMerchantEnterApplyPo tbMerchantEnterApplyPo = tbMerchantEnterApplyPos.get(0);
            Integer auditState = tbMerchantEnterApplyPo.getAuditState();
            if (AuditStateEnum.WAIT_AUDIT.getValue().equals(auditState)) {
                preApplyMerchantVo.setState(1);
                preApplyMerchantVo.setMsg("您已提交入驻申请，正在审核中");
            }

            if (AuditStateEnum.FAIL.getValue().equals(auditState)) {
                // 判断是否是同个邀请码入驻的
                if (!tbMerchantEnterApplyPo.getSettleCode().equals(settleCode)) {
                    Integer systemAuditState = tbMerchantEnterApplyPo.getSystemAuditState();
                    // 商户入驻同时间只能申请一个，商家拒绝，就算一次完结，再点邀请，就进新的入驻，汇付侧的什么失败，就进失败重新提交
                    if (!SystemAuditStateEnum.MANAGER_AUDIT_FAIL.getValue().equals(systemAuditState)) {
                        preApplyMerchantVo.setState(2);
                    } else {
                        preApplyMerchantVo.setState(4);
                    }
                } else {
                    preApplyMerchantVo.setState(2);
                    preApplyMerchantVo.setMsg("入驻审核拒绝，请重新申请");
                }
            }

            if (AuditStateEnum.SUCCESS.getValue().equals(auditState)) {
                // 判断是否是同个邀请码入驻的
                if (tbMerchantEnterApplyPo.getSettleCode().equals(settleCode)) {
                    preApplyMerchantVo.setState(3);
                    preApplyMerchantVo.setMsg("入驻审核成功，请登录");
                }
            }
        }

        return preApplyMerchantVo;
    }

    @Override
    public Boolean repeatApply(MerchantEnterRepeatApplyDto merchantEnterRepeatApplyDto) {
        Long merchantId = merchantEnterRepeatApplyDto.getMerchantId();
        String openid = merchantEnterRepeatApplyDto.getOpenid();
        String settleCode = merchantEnterRepeatApplyDto.getSettleCode();
        String applyIp = merchantEnterRepeatApplyDto.getApplyIp();

        TbMerchantPo tbMerchantPo = merchantMapper.selectById(merchantId);
        if (tbMerchantPo == null || tbMerchantPo.getDelState() != 0) {
            Throw.isBusinessException("请先成为商户");
        }

        List<TbBusinessPo> tbBusinessPos = businessMapper.selectList(new QueryWrapper<TbBusinessPo>().eq("del_state", 0)
                .eq("invite_code", settleCode));
        TbBusinessPo tbBusinessPo = tbBusinessPos.get(0);
        Long businessId = tbBusinessPo.getId();
        LocalDateTime now = LocalDateTime.now();

        // 查询审核成功的商户入驻数据，如果是商家入驻同步创建的商户，则没有商户入驻数据，如果再被其他商家邀请入驻为商户，则不用新增商户入驻申请记录
        List<TbMerchantEnterApplyPo> tbMerchantEnterApplyPos = baseMapper.selectList(new QueryWrapper<TbMerchantEnterApplyPo>().eq("del_state", 0)
                .eq("openid", tbMerchantPo.getOpenid()).eq("audit_state", AuditStateEnum.SUCCESS.getValue()).orderByDesc("apply_time"));
//        if (CollectionUtils.isEmpty(tbMerchantEnterApplyPos)) {
//            Throw.isBusinessException("请先成为商户");
//        }

        // 查询是否已经与商家关联
        Integer count = businessMerchantMapper.selectCount(new QueryWrapper<TbBusinessMerchantPo>().eq("del_state", 0)
                .eq("merchant_id", merchantId).eq("business_id", businessId));
        if (count != null && count > 0) {
            return true;
        }

        TransactionStatus transaction = transactionManager.getTransaction(new DefaultTransactionAttribute());

        try {
            if (!CollectionUtils.isEmpty(tbMerchantEnterApplyPos)) {
                TbMerchantEnterApplyPo tbMerchantEnterApplyPo = tbMerchantEnterApplyPos.get(0);
                TbMerchantEnterApplyPo newMerchantEnterApplyPo = new TbMerchantEnterApplyPo();
                BeanUtils.copyProperties(tbMerchantEnterApplyPo, newMerchantEnterApplyPo);
                newMerchantEnterApplyPo.setSettleCode(settleCode);
                newMerchantEnterApplyPo.setApplyNo(NoUtils.getMerchantEnterApplyNo());
                newMerchantEnterApplyPo.setApplyIp(applyIp);
                newMerchantEnterApplyPo.setAuditState(AuditStateEnum.SUCCESS.getValue());
                newMerchantEnterApplyPo.setSystemAuditState(SystemAuditStateEnum.HF_ENTER_AUDIT_SUCCESS.getValue());
                newMerchantEnterApplyPo.setApplyTime(now);
                newMerchantEnterApplyPo.setCreateTime(now);
                int insert = baseMapper.insert(tbMerchantEnterApplyPo);
                if (insert == 0) {
                    Throw.isBusinessException("商户入驻申请失败");
                }
            }

            // 新增关联tb_business_merchant
            TbBusinessMerchantPo tbBusinessMerchantPo = new TbBusinessMerchantPo();
            tbBusinessMerchantPo.setMerchantId(merchantId);
            tbBusinessMerchantPo.setBusinessId(businessId);
            tbBusinessMerchantPo.setTotalOrderAmt(BigDecimal.ZERO);
            tbBusinessMerchantPo.setTotalOrderCount(0);
            tbBusinessMerchantPo.setOwnState(OwnStateEnum.NO.getValue());
            tbBusinessMerchantPo.setCreateTime(now);
            count = businessMerchantMapper.insert(tbBusinessMerchantPo);
            if (count == 0) {
                log.error("新增商户商家关联数据失败");
                Throw.isBusinessException("商户入驻申请失败");
            }

            transactionManager.commit(transaction);
        } catch (Exception e) {
            //回滚事务
            transactionManager.rollback(transaction);
            log.error("<商户入驻申请新的商家>事务异常回滚", e);
            Throw.isBusinessException(e.getMessage());
        }

        return true;
    }

    @Override
    public List<MerchantEnterApplyPageVo> listByApplyNoAndHfId(String hfApplyNo, String hfMerchantNo) {
        return baseMapper.listByApplyNoAndHfId(hfApplyNo, hfMerchantNo);
    }

    @Override
    public Boolean updateMerchantEnterApplyById(MerchantEnterApplyUpdateDto merchantEnterApplyUpdateDto) {
        TbMerchantEnterApplyPo tbMerchantEnterApplyPo = baseMapper.selectById(merchantEnterApplyUpdateDto.getId());
        if (tbMerchantEnterApplyPo == null) {
            Throw.isBusinessException("未找到商户入驻信息");
        }

        BeanUtils.copyProperties(merchantEnterApplyUpdateDto, tbMerchantEnterApplyPo);
        tbMerchantEnterApplyPo.setUpdateTime(LocalDateTime.now());
        int update = baseMapper.updateById(tbMerchantEnterApplyPo);
        if (update == 0) {
            Throw.isBusinessException("更新商户入驻信息失败");
        }

        return true;
    }

    @Override
    public MerchantEnterApplyVo getEnterInfoByOpenid(String openid) {
        if (StringUtils.isBlank(openid)) {
            Throw.isBusinessException("请先授权");
        }

        List<TbMerchantPo> tbMerchantPos = merchantMapper.selectList(new QueryWrapper<TbMerchantPo>().eq("del_state", 0)
                .eq("openid", openid));
        if (!CollectionUtils.isEmpty(tbMerchantPos)) {
            MerchantEnterApplyVo merchantEnterApplyVo = new MerchantEnterApplyVo();

            // 判断是否需要弹窗
            Integer count = popRecordMapper.selectCount(new QueryWrapper<TbPopRecordPo>()
                    .eq("platform_type", PlatformTypeEnum.MERCHANT.getValue())
                    .eq("pop_type", PopTypeEnum.MERCHANT_ENTER.getValue())
                    .eq("user_id", tbMerchantPos.get(0).getId()));
            if (count == null || count == 0) {
                merchantEnterApplyVo.setPopState(true);
            }

            merchantEnterApplyVo.setMerchantState(true);
            return merchantEnterApplyVo;
        }

        List<TbMerchantEnterApplyPo> tbMerchantEnterApplyPos = baseMapper.selectList(new QueryWrapper<TbMerchantEnterApplyPo>().eq("del_state", 0)
                .eq("openid", openid).orderByDesc("apply_time"));
        if (CollectionUtils.isEmpty(tbMerchantEnterApplyPos)) {
            MerchantEnterApplyVo merchantEnterApplyVo = new MerchantEnterApplyVo();
            merchantEnterApplyVo.setPopState(false);
            merchantEnterApplyVo.setMerchantState(false);
            return merchantEnterApplyVo;
        }

        TbMerchantEnterApplyPo tbMerchantEnterApplyPo = tbMerchantEnterApplyPos.get(0);
        MerchantEnterApplyVo merchantEnterApplyVo = new MerchantEnterApplyVo();
        BeanUtils.copyProperties(tbMerchantEnterApplyPo, merchantEnterApplyVo);

        Integer auditState = merchantEnterApplyVo.getAuditState();
        if (AuditStateEnum.SUCCESS.getValue().equals(auditState)) {
            if (!CollectionUtils.isEmpty(tbMerchantPos)) {
                // 判断是否需要弹窗
                Integer count = popRecordMapper.selectCount(new QueryWrapper<TbPopRecordPo>()
                        .eq("platform_type", PlatformTypeEnum.MERCHANT.getValue())
                        .eq("pop_type", PopTypeEnum.MERCHANT_ENTER.getValue())
                        .eq("user_id", tbMerchantPos.get(0).getId()));
                if (count == null || count == 0) {
                    merchantEnterApplyVo.setPopState(true);
                }
            }
        }

        return merchantEnterApplyVo;
    }

    @Override
    public MerchantEnterApplyVo getSuccessEnterInfoByOpenid(String openid) {
        List<TbMerchantEnterApplyPo> tbMerchantEnterApplyPos = baseMapper.selectList(new QueryWrapper<TbMerchantEnterApplyPo>().eq("del_state", 0)
                .eq("audit_state", AuditStateEnum.SUCCESS.getValue())
                .eq("openid", openid).orderByDesc("apply_time"));
        if (!CollectionUtils.isEmpty(tbMerchantEnterApplyPos)) {
            MerchantEnterApplyVo merchantEnterApplyVo = new MerchantEnterApplyVo();
            BeanUtils.copyProperties(tbMerchantEnterApplyPos.get(0), merchantEnterApplyVo);
            return merchantEnterApplyVo;
        }

        return null;
    }
}
